/**
* AutoSWF - Cody Cushing. March 26, 2009
* Copyright (c) 2009 Cody Cushing
* No use restrictions. Maintain this notice in all versions. 
**/

package com.autoswf.dispatcher
{
	import com.autoswf.core.Link;
	import com.autoswf.core.Transport;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.utils.Dictionary;
	import flash.utils.getQualifiedClassName;

	
	/**
	 * Allows type safe event listeners. An event instance has to match class type and string type
	 * to trigger a handler.
	 */	
	public class TypedDispatcher extends Link
	{
		protected var _dispatchers:Dictionary;
		
		
		/**
		 * Constructor. 
		 */		
		public function TypedDispatcher(id:String)
		{
			super(id);
			
			_dispatchers = new Dictionary(false);
		}


		public function addTypedListener(classDef:Class, type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false):void
		{
			var classDefAlias:String = getQualifiedClassName(classDef);
			if(_dispatchers[classDefAlias] == null)
			{
				_dispatchers[classDefAlias] = new EventDispatcher();
			}
			
			IEventDispatcher(_dispatchers[classDefAlias]).addEventListener(type, listener, useCapture, priority, useWeakReference);
		}
		
		
		public function removeTypedListener(classDef:Class, type:String, listener:Function, useCapture:Boolean=false):void
		{
			var classDefAlias:String = getQualifiedClassName(classDef);
			if(_dispatchers.hasOwnProperty(classDefAlias))
			{
				IEventDispatcher(_dispatchers[classDefAlias]).removeEventListener(type, listener, useCapture);
			}
		}
		
		
		public function dispatchTypedEvent(event:Event):void
		{
			var classDefAlias:String = getQualifiedClassName(event);
			var dispatcher:IEventDispatcher = _dispatchers[classDefAlias];
			
			if(dispatcher != null)
			{
				dispatcher.dispatchEvent(event);
			}
		}
		
		
		override public function sendUp(object:*):void
		{
			var transport:Transport = (object is Transport) ? object : new Transport(object);
			
			if(transport.message is Event)
			{
				dispatchTypedEvent(transport.message);
			}
			
			notifyParents(transport);
		}
		
	}
}